<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>修勾夜店</title>
    <script src="https://www.jq22.com/jquery/jquery-1.10.2.js"></script>
    <script type="text/javascript" th:src="@{/js/decode.js}"></script>
    <style>
    </style>
</head>
<body>
    <input type="hidden" id="roomid" th:value="${roomId}">
    <input type="hidden" id="token" th:value="${token}">
    <input type="hidden" id="url" th:value="${url}">
    <div id="music"></div>
    <div id="wutai" style="width: 100%;height: 1080px;position:absolute;">
        <div style="width: 100%;height: 50%">
            <img th:src="@{/img/bg2.jpg}" style="width: 100%;height: 100%">
        </div>
        <div style="width: 100%;height: 50%">
            <img th:src="@{/img/bg1.png}" style="width: 100%;height: 100%">
        </div>
        <div style="  position: absolute;left: 40%;top: 35%;">
            <img th:src="@{/img/dj.gif}">
        </div>
        <canvas id="canvas" width="1920" height="950"></canvas><style>canvas {display: block;position: relative;zindex: 1;pointer-events: none;position: fixed;top: 0;}</style>
        <script th:src="@{/js/confetti.js}"></script>
        <div id="xiugo" style="width: 5%;position:absolute;top: 40%;left: 0px;text-align: center;">
            <p id="xiugo_message"></p>
            <p style="color: azure">修勾</p>
            <img th:src="@{/img/gif/dog2.gif}" style="width:100%">
        </div>
    </div>
</body>
<!--音乐轮播js-->
<script type="text/javascript">
    window.onload = function(){
        //存放音乐列表，根据音乐文件路径，进行填写
        var musicList = ["/music/周杰伦 - 飘移.mp3","/music/周杰伦 - 秘密花园 (《大灌篮》电影插曲).mp3"]
        playMusic(musicList);
    }

    function playMusic(musicList){
        var myAudio = new Audio();
        //是否进行预加载
        myAudio.preload = false;
        //是否显示隐藏按钮
        myAudio.controls = true;
        myAudio.hidden = false;
        //从音乐列表中，获取最后一个音乐（并删除）
        var src = musicList.pop();
        myAudio.src =src;
        //将最后一个音乐添加到数组的开头，这样实现循环
        musicList.unshift(src);
        //绑定音乐结束事件，当音乐播放完成后，将会触发playEndedHandler方法
        myAudio.addEventListener("ended",playEndedHandler,false);

        document.getElementById("music").appendChild(myAudio);
        //
        // //播放当前音乐
        myAudio.play();
        //将循环播放关闭，如果开启，将不能触发playEndedHandler方法，只能进行单曲循环
        myAudio.loop = false;

        function playEndedHandler(){
            src = musicList.pop();
            myAudio.src = src;
            musicList.unshift(src);
            myAudio.play();
        }
    }

    //解决谷歌浏览器音乐不能自动播放的问题，
    function musicAutoPlay(){
        let music = document.getElementById('music')//获取audio
        if (music.paused) {//判断一下paused（pused为真是禁用的）
            music.play()//调用播放
        }
    }
    setInterval("musicAutoPlay()", 10);//必须使用一个时间函数 ，不触发的情况下还是报错

    //

</script>

<!--监听弹幕js-->
<script type="text/javascript">
    let token = document.getElementById("token").value;
    let url = document.getElementById("url").value;
    let roomid = document.getElementById("roomid").value;

    var eventTarget = new EventTarget();

    //事件注册
    function on(eventType, callback){
        eventTarget.addEventListener(eventType, function(e){
            callback(e.detail);
        });
    }

    //生成认证数据
    function getCertification(json){
        let encoder = new TextEncoder();    //编码器
        let jsonView = encoder.encode(json);    //utf-8编码
        let buff = new ArrayBuffer(jsonView.byteLength + 16);    //数据包总长度：16位头部长度+bytes长度
        let view = new DataView(buff);    //新建操作视窗
        view.setUint32(0, jsonView.byteLength + 16);    //整个数据包长度
        view.setUint16(4, 16);    //头部长度
        view.setUint16(6, 1);    //协议版本
        view.setUint32(8, 7);    //类型,7为加入房间认证
        view.setUint32(12, 1);    //填1
        for(let r = 0; r < jsonView.byteLength; r++){
            view.setUint8(16 + r, jsonView[r]);    //填入数据
        }
        return buff;
    }

    function handleMessage(blob, call){
        let reader = new FileReader();
        reader.onload = function(e){
            let buff = e.target.result;    //ArrayBuffer对象
            let decoder = new TextDecoder();    //解码器
            let view = new DataView(buff);    //视图
            let offset = 0;
            let packet = {};
            let result = [];
            while (offset < buff.byteLength){    //数据提取
                let packetLen = view.getUint32(offset + 0);
                let headLen = view.getUint16(offset + 4);
                let packetVer = view.getUint16(offset + 6);
                let packetType = view.getUint32(offset + 8);
                let num = view.getUint32(12);
                if (packetVer == 3){    //解压数据
                    let brArray = new Uint8Array(buff, offset + headLen, packetLen - headLen);
                    let BrotliDecode = makeBrotliDecode();    //生成Brotli格式解压工具的实例
                    let buffFromBr = BrotliDecode(brArray);    //返回Int8Array视图
                    let view = new DataView(buffFromBr.buffer);
                    let offset_Ver3 = 0;
                    while (offset_Ver3 < buffFromBr.byteLength){    //解压后数据提取
                        let packetLen = view.getUint32(offset_Ver3 + 0);
                        let headLen = view.getUint16(offset_Ver3 + 4);
                        let packetVer = view.getUint16(offset_Ver3 + 6);
                        let packetType = view.getUint32(offset_Ver3 + 8);
                        let num = view.getUint32(12);
                        packet.Len = packetLen;
                        packet.HeadLen = headLen;
                        packet.Ver = packetVer;
                        packet.Type = packetType;
                        packet.Num = num;
                        let dataArray = new Uint8Array(buffFromBr.buffer, offset_Ver3 + headLen, packetLen - headLen);
                        packet.body = decoder.decode(dataArray);    //utf-8格式数据解码，获得字符串
                        result.push(JSON.stringify(packet));    //数据打包后传入数组
                        offset_Ver3 += packetLen;
                    }
                }else{
                    packet.Len = packetLen;
                    packet.HeadLen = headLen;
                    packet.Ver = packetVer;
                    packet.Type = packetType;
                    packet.Num = num;
                    let dataArray = new Uint8Array(buff, offset + headLen, packetLen - headLen);
                    if (packetType == 3){    //获取人气值
                        packet.body = (new DataView(buff, offset + headLen, packetLen - headLen)).getUint32(0);    //若入参为dataArray.buffer，会返回整段buff的视图，而不是截取后的视图
                    }else{
                        packet.body = decoder.decode(dataArray);    //utf-8格式数据解码，获得字符串
                    }
                    result.push(JSON.stringify(packet));    //数据打包后传入数组
                }
                offset += packetLen;
            }
            call(result);    //数据后续处理
        }
        reader.readAsArrayBuffer(blob);    //读取服务器传来的数据转换为ArrayBuffer
    }

    function webSocket(room_id){

        if("WebSocket" in window){
            console.log("您的浏览器支持WebSocket");
            var timer;    //心跳包定时器
            var ws = new WebSocket(url);

            //连接成功后发送认证信息和设置心跳包定时器
            ws.onopen = function(e){
                console.log("open");
                var certification = {
                    "uid": 0,
                    "roomid": room_id,
                    "protover": 3,
                    "platform": "web",
                    "type": 2,
                    "key": token
                }
                ws.send(getCertification(JSON.stringify(certification)));
                console.log(JSON.stringify(certification))
                //发送心跳包
                timer = setInterval(function(){
                    let buff = new ArrayBuffer(16);
                    let i = new DataView(buff);
                    i.setUint32(0, 0);    //整个封包
                    i.setUint16(4, 16);    //头部
                    i.setUint16(6, 1);    //协议版本
                    i.setUint32(8, 2);    //操作码,2为心跳包
                    i.setUint32(12, 1);    //填1
                    ws.send(buff);
                }, 30000); //30秒
            }


            //连接关闭后停止心跳包定时器
            ws.onclose = function(e){
                //当客户端收到服务端发送的关闭连接请求时，触发onclose事件
                console.log("close");
                if (timer != null){
                    clearInterval(timer);    //停止发送心跳包
                }
                setTimeout(webSocket,4000);    //4秒后重连，按需设置或不重连
            }



            //数据处理
            ws.onmessage = function(e){
                //当客户端收到服务端发来的消息时，触发onmessage事件，参数e.data包含server传递过来的数据
                console.log(e.data);
                let blob = e.data;
                handleMessage(blob, function(result){
                    //触发事件
                    for(let i=0; i<result.length; i++){
                        let json = JSON.parse(result[i]);
                        console.log(JSON.parse(json.body).cmd);
                        if (json.Type == 5){
                            let event = new CustomEvent(JSON.parse(json.body).cmd, {detail: JSON.parse(json.body)});
                            eventTarget.dispatchEvent(event);
                        }
                        if (json.Type == 8){
                            let event = new CustomEvent("Certify_Success", {detail: JSON.parse(json.body)});
                            eventTarget.dispatchEvent(event);
                        }
                        if (json.Type == 3){
                            let event = new CustomEvent("VIEW", {detail: json.body});
                            eventTarget.dispatchEvent(event);
                        }
                    }
                });
            }


            ws.onerror = function(e){
                //如果出现连接、处理、接收、发送数据失败的时候触发onerror事件
                console.log(e);
            }

            //认证成功事件
            on("Certify_Success", function(e){
                let data = e;
                if (data.code == 0){
                    console.log("Certify_Success");
                }
            })
//人气值刷新事件
            on("VIEW", function(e){
                let data = e;
                console.log("VIEW: " + data.toString());
            })

//进入直播间或关注直播间事件
            on("INTERACT_WORD", function(e){
                let data = e;
                let uname = data.data.uname;
                let timedata = new Date(data.data.timestamp * 1000);
                let time = timedata.toLocaleDateString() + " " + timedata.toTimeString().split(" ")[0];
                if (data.data.msg_type == 2){
                    console.log(time+ " " + uname + " 关注直播间");
                }else{
                    console.log(data.cmd + " " + time+ " " + uname + " 进入直播间");
                    createDog(uname);
                }
            })
            function createDog(uname) {
                //创建修勾
                let wutai=document.getElementById('wutai');
                let x = Math.random()*95-10;
                let y = Math.random()*50+40;
                let dog=Math.round(Math.random()*3)+1;
                let addDiv='<div id="'+uname+'_xiugo" style="width: 25%;position:absolute;top: '+y+'%;left: '+x+'%;text-align: center;">\n' +
                    '            <p id="'+uname+'_message" style="background-color: white; border-radius: 3px" ></p>'+
                    '            <p style="color: azure">'+uname+'</p>\n' +
                    '            <img id="'+uname+'_image" src="/img/gif/dog'+dog+'.gif" style="width:20%">\n' +
                    '        </div>'
                wutai.insertAdjacentHTML('beforeend',addDiv);
            }


//弹幕事件
            on("DANMU_MSG", function(e){
                let data = e;
                let uname = data.info[2][1];
                let timedata = new Date(data.info[9].ts * 1000);
                let time = timedata.toLocaleDateString() + " " + timedata.toTimeString().split(" ")[0];
                let text = data.info[1];
                console.log(data.cmd + " " + time+ " " + uname + " :" + text);
                if (text==='换修勾'){
                    resetDog(uname);
                    return;
                }
                //显示文字
                let msg = document.getElementById(uname+'_message');
                if (msg==null){
                    createDog(uname);
                    msg = document.getElementById(uname+'_message');
                }
                msg.innerText=text;
                msg.style.visibility='visible';
                setTimeout(function (){
                    f(uname);
                },3000);
            })
            function f(e){
                let msg = document.getElementById(e+'_message');
                msg.style.visibility='hidden';
            }

            function resetDog(uname) {
                let img = document.getElementById(uname+'_image');
                let dog=Math.round(Math.random()*3)+1;
                img.src='/img/gif/dog'+dog+'.gif';
            }

//礼物赠送事件
            on("SEND_GIFT", function(e){
                let data = e;
                let uname = data.data.uname;
                let gift_num = data.data.num;
                let act = data.data.action;
                let gift_name = data.data.giftName;
                let timedata = new Date(data.data.timestamp * 1000);
                let time = timedata.toLocaleDateString() + " " + timedata.toTimeString().split(" ")[0];
                console.log(data.cmd + " " + time+ " " + uname + " :" + act + " " + gift_num + " " + gift_name);
            })
        }else{
            console.log("您的浏览器不支持WebSocket");
        }

    }
    webSocket(parseInt(roomid))
</script>

</html>